package br.com.foxinline.manager.criar;

import br.com.foxinline.enums.StatusColetaDados;
import br.com.foxinline.modelo.*;
import br.com.foxinline.servico.ColetaDadosServico;
import br.com.foxinline.servico.CoordenadaServico;
import br.com.foxinline.servico.PrefeituraServico;
import br.com.foxinline.servico.QuadraServico;
import br.com.foxinline.servico.SituacaoColetaDadosServico;
import br.com.foxinline.servico.UsuarioServico;
import br.com.foxinline.util.Conexao;
import br.com.foxinline.util.Msg;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import org.primefaces.event.map.OverlaySelectEvent;
import org.primefaces.event.map.PointSelectEvent;
import org.primefaces.event.map.StateChangeEvent;
import org.primefaces.model.map.*;

/**
 *
 * @author roniere
 */
@ManagedBean
@ViewScoped
public class ManagerMapaColetaDados {

    @EJB
    private ColetaDadosServico coletaDadosServico;
    @EJB
    private SituacaoColetaDadosServico situacaoColetaDadosServico;
    @EJB
    private CoordenadaServico coordenadaServico;
    @EJB
    private QuadraServico quadraServico;
    @EJB
    private UsuarioServico usuarioServico;
    @EJB
    private PrefeituraServico prefeituraServico;
    private String centroMapa;
    private DefaultMapModel mapModel;
    private int zoomLevelMapa;
    private Polygon polygon;
    private Setor setor;
    private Quadra quadra;
    private SituacaoColetaDados situacaoColetaDados;
    /**
     * Atualização de Coleta
     */
    private SituacaoColetaDados situacaoColetaDadosAtualizar;
    private Usuario usuarioAtualizar;
    private boolean connect;

    @PostConstruct
    public void init() {
        this.mapModel = new DefaultMapModel();
        this.situacaoColetaDadosAtualizar = new SituacaoColetaDados();

        this.centroMapa = prefeituraServico.getCentroMapa();
        this.zoomLevelMapa = prefeituraServico.getZoomMapa();

        if (prefeituraServico.find().getDesabilitarMapas()) {

            this.connect = false;
        } else if (!Conexao.isInternetReachable()) {

            this.connect = false;
            Msg.messagemWarn("Não foi possível estabelecer uma conexão com a Internet.");
        } else {
            this.connect = true;
        }
    }

    private void initAtualizar() {
        this.situacaoColetaDadosAtualizar = new SituacaoColetaDados();
        this.usuarioAtualizar = null;
    }

    public void onStateChange(StateChangeEvent event) {
        this.zoomLevelMapa = event.getZoomLevel();
        this.centroMapa = event.getCenter().getLat() + ", " + event.getCenter().getLng();
    }

    public void handlePointClick(PointSelectEvent event) {

        LatLng latLng = event.getLatLng();

        addOverlayToMapModel(new Marker(latLng));

        this.mapModel.addOverlay(this.polygon);

        for (Marker premarker : this.mapModel.getMarkers()) {
            premarker.setDraggable(true);
        }

    }

    private void addOverlayToMapModel(Marker marker) {
        this.mapModel.addOverlay(marker);
        this.polygon.getPaths().add(marker.getLatlng());
        this.polygon.setStrokeColor("#FF9900");
        this.polygon.setFillColor("#FF9900");
        this.polygon.setFillOpacity(0.2);
    }

    public void mapearSetorQuadras() {
        this.mapModel = new DefaultMapModel();
        List<Coordenada> coordenadas = coordenadaServico.find(setor);
        List<Quadra> quadras = quadraServico.find(setor);
        List<SituacaoColetaDados> situacoes;
        Double lat = 0.0, log = 0.0;

        adicionarPolilyneMapModel(coordenadas, false, null, null);

        for (Coordenada coordenada : coordenadas) {
            lat += coordenada.getLat();
            log += coordenada.getLog();
        }

        this.zoomLevelMapa = 15;
        this.centroMapa = lat / coordenadas.size() + ", " + log / coordenadas.size();

        for (Quadra q : quadras) {
            situacoes = situacaoColetaDadosServico.buscarSituacao(q.getId());
            String cor = null;
            if (situacoes != null && !situacoes.isEmpty()) {
                if (situacoes.get(0).getStatusColetaDados() == StatusColetaDados.COLETA_EM_CAMPO) {
                    cor = "#E661AC";
                } else if (situacoes.get(0).getStatusColetaDados() == StatusColetaDados.CONFERENCIA) {
                    cor = "#FDF569";
                } else if (situacoes.get(0).getStatusColetaDados() == StatusColetaDados.PENDENTE) {
                    cor = "#F43224";
                } else if (situacoes.get(0).getStatusColetaDados() == StatusColetaDados.TOPOGRAFIA) {
                    cor = "#FCA752";
                } else if (situacoes.get(0).getStatusColetaDados() == StatusColetaDados.CONCLUIDO) {
                    cor = "#00FF00";
                }
            }

            adicionarPolilyneMapModel(coordenadaServico.find(q), true, q.getNumero(), cor);
        }
    }

    public void onMarkerSelect(OverlaySelectEvent event) {
        try {
            Marker marker = (Marker) event.getOverlay();
            quadra = quadraServico.findByName("" + marker.getData(), setor).get(0);
            situacaoColetaDados = situacaoColetaDadosServico.buscarUltimaSituacao(quadra.getId());

        } catch (Exception e) {
            System.err.println(e);
        }
    }

    private void adicionarPolilyneMapModel(List<Coordenada> coordenadas, boolean adicionarMarker, Integer numeroQuadra, String corQuadra) {

        if (!coordenadas.isEmpty()) {

            LatLng coord;
            Polyline polyline = new Polyline();
            Polygon polygon = new Polygon();

            Double lat = 0.0, lng = 0.0;

            for (Coordenada c : coordenadas) {
                coord = new LatLng(c.getLat(), c.getLog());

                if (adicionarMarker) {
                    lat += coord.getLat();
                    lng += coord.getLng();
                }

                polyline.getPaths().add(coord);
            }

            coord = new LatLng(coordenadas.get(0).getLat(), coordenadas.get(0).getLog());
            polyline.getPaths().add(coord);
            polyline.setStrokeWeight(4);

            if (!adicionarMarker) {
                //SETOR
                polyline.setStrokeColor("#ff0000");
            } else {
                //QUADRA
                polyline.setStrokeColor(corQuadra == null ? "#1B93DF" : corQuadra);

            }

            polyline.setStrokeOpacity(0.7);

            mapModel.addOverlay(polyline);

            ExternalContext context = FacesContext.getCurrentInstance().getExternalContext();

            if (adicionarMarker) {
                coord = new LatLng(lat / coordenadas.size(), lng / coordenadas.size());

                Marker mk = new Marker(coord, "", Quadra.class.getSimpleName(),
                        "http://" + context.getRequestServerName() + ":" + context.getRequestServerPort() + "/Atlas-war/media/images/quadra/quadra_" + numeroQuadra + ".gif");

                mk.setDraggable(false);
                mk.setData(numeroQuadra);
                this.mapModel.addOverlay(mk);
            }
        }
    }

    public void atualizarColeta() {
        try {

            ColetaDados coletaDados = coletaDadosServico.buscarColetaDados(quadra.getId());

            situacaoColetaDadosAtualizar.setCriadoPor(usuarioServico.getCurrentUser());
            situacaoColetaDadosAtualizar.setDataCriacao(new Date());
            situacaoColetaDadosAtualizar.setUsuarioAgente(usuarioAtualizar);

            if (coletaDados != null) {

                coletaDados.getSituacaoColetaDados().add(situacaoColetaDadosAtualizar);
                coletaDadosServico.update(coletaDados);

            } else {

                coletaDados = new ColetaDados();

                coletaDados.setCriadoPor(usuarioServico.getCurrentUser());
                coletaDados.setDataCriacao(new Date());
                coletaDados.setQuadra(quadra);

                List<SituacaoColetaDados> list = new ArrayList<SituacaoColetaDados>();
                list.add(situacaoColetaDadosAtualizar);

                coletaDados.setSituacaoColetaDados(list);

                coletaDadosServico.save(coletaDados);
            }

            Msg.messagemInfo(Msg.SuccessFull);
            mapearSetorQuadras();

        } catch (Exception e) {
            System.err.println(e);
            Msg.messagemInfo(Msg.Failure);
        }
    }

    public Polygon getPolygon() {
        return polygon;
    }

    public void setPolygon(Polygon polygon) {
        this.polygon = polygon;
    }

    public Setor getSetor() {
        return setor;
    }

    public void setSetor(Setor setor) {
        this.setor = setor;
    }

    public Quadra getQuadra() {
        return quadra;
    }

    public void setQuadra(Quadra quadra) {
        this.quadra = quadra;
    }

    public SituacaoColetaDados getSituacaoColetaDados() {
        return situacaoColetaDados;
    }

    public void setSituacaoColetaDados(SituacaoColetaDados situacaoColetaDados) {
        this.situacaoColetaDados = situacaoColetaDados;
    }

    public SituacaoColetaDados getSituacaoColetaDadosAtualizar() {
        return situacaoColetaDadosAtualizar;
    }

    public void setSituacaoColetaDadosAtualizar(SituacaoColetaDados situacaoColetaDadosAtualizar) {
        this.situacaoColetaDadosAtualizar = situacaoColetaDadosAtualizar;
    }

    public Usuario getUsuarioAtualizar() {
        return usuarioAtualizar;
    }

    public void setUsuarioAtualizar(Usuario usuarioAtualizar) {
        this.usuarioAtualizar = usuarioAtualizar;
    }

    public String getCentroMapa() {
        return centroMapa;
    }

    public void setCentroMapa(String centroMapa) {
        this.centroMapa = centroMapa;
    }

    public DefaultMapModel getMapModel() {
        return mapModel;
    }

    public void setMapModel(DefaultMapModel mapModel) {
        this.mapModel = mapModel;
    }

    public int getZoomLevelMapa() {
        return zoomLevelMapa;
    }

    public void setZoomLevelMapa(int zoomLevelMapa) {
        this.zoomLevelMapa = zoomLevelMapa;
    }

    public boolean isConnect() {
        return connect;
    }

    public void setConnect(boolean connect) {
        this.connect = connect;
    }
}
